﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "../macro/head.h"
#include "odbc_mgr.h"
#include "odbc_dbc.h"

namespace xos_odbc
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    odbc_mgr::odbc_mgr()
    {
        init_data();
    }

    odbc_mgr::~odbc_mgr()
    {
        if( g_pSysData )
        {
            g_pSysData->term();
            delete g_pSysData;
            g_pSysData = 0;
        }
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int odbc_mgr::prepare_connect( void * hWnd, const char * lpszConnectStr, bool bAsync, i_dbc ** ppDbc )
    {
        int ret = 0;

        i_dbc * pDbc = 0;

        if( 0 == ret )
        {
            ret = create_connect( hWnd, lpszConnectStr, bAsync, &pDbc );
        }

        if( ( 0 == ret ) && bAsync )
        {
            ret = pDbc->set_connect_fun_async( bAsync );
        }

        if( ( 0 == ret ) && ppDbc )
        {
            *ppDbc = pDbc;
            pDbc = 0;
        }

        xos_stl::release_interface( pDbc );

        return ret;
    }

    int odbc_mgr::connect( void * hWnd, const char * lpszConnectStr, bool bAsync, i_dbc ** ppDbc )
    {
        int ret = 0;

        i_dbc * pDbc = 0;

        if( 0 == ret )
        {
            ret = create_connect( hWnd, lpszConnectStr, bAsync, &pDbc );
        }

        if( 0 == ret )
        {
            ret = pDbc->connect();
        }

        if( ( 0 == ret ) && ppDbc )
        {
            *ppDbc = pDbc;
            pDbc = 0;
        }

        xos_stl::release_interface( pDbc );

        return ret;
    }

    // 
    // 得到最近的错误信息
    // 
    int odbc_mgr::get_last_err_info( char * lpszInfo, int nSize, int * lpnInfoLen, int * lpnLenNeeded )
    {
        int ret = 0;

        if( 0 == ret )
        {
            m_err.get_info( lpszInfo, nSize, lpnInfoLen, lpnLenNeeded );
        }

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int odbc_mgr::put_back_to_pool( T * pT, bool bLock )
    {
        int ret = 0;
        delete this;
        return ret;
    }

    // 
    // init env
    // 
    int odbc_mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            g_pSysData->m_pContainer->log()->add_log_module( LOG_NAME, 1 );
            g_pSysData->m_pContainer->log()->add_log_module( LOG_NAME, 2 );
            g_pSysData->m_pContainer->log()->add_log_module( LOG_NAME, 3 );
            g_pSysData->m_pContainer->log()->add_log_module( LOG_NAME, 4 );
        }

        if( 0 == ret )
        {
            ret = init_env();
        }

        return ret;
    }

    int odbc_mgr::term()
    {
        int ret = 0;

        term_env();
        init_data();

        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int odbc_mgr::create_connect( void * hWnd, const char * lpszConnectStr, bool bAsync, i_dbc ** ppDbc )
    {
        int ret = 0;

        SQLHANDLE hDbc = SQL_NULL_HDBC;

        if( ( 0 == ret ) && ( SQL_NULL_HANDLE == m_hEnv ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLAllocHandle( SQL_HANDLE_DBC, m_hEnv, &hDbc );
            ret = m_err.connect_ret( hDbc, r );
        }

        if( ( 0 == ret ) && ppDbc )
        {
            odbc_dbc::T * p = odbc_dbc::get_item_from_pool( true );
            p->set_connect_info( hWnd, lpszConnectStr, bAsync );
            p->set_handle( hDbc );
            p->init();
            *ppDbc = p;
            hDbc = SQL_NULL_HDBC;
        }

        if( SQL_NULL_HDBC != hDbc )
        {
            SQLDisconnect( hDbc );
            SQLFreeHandle( SQL_HANDLE_DBC, hDbc );
            hDbc = SQL_NULL_HDBC;
        }

        return ret;
    }

    int odbc_mgr::init_data()
    {
        int ret = 0;
        m_hEnv = SQL_NULL_HANDLE;
        m_err.clear();
        return ret;
    }

    int odbc_mgr::init_env()
    {
        int ret = 0;

        if( 0 == ret )
        {
            SQLRETURN r = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_hEnv );
            ret = m_err.env_ret( m_hEnv, r );
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLSetEnvAttr( m_hEnv, SQL_ATTR_ODBC_VERSION, ( SQLPOINTER )SQL_OV_ODBC3, 0 );
            ret = m_err.env_ret( m_hEnv, r );
        }

        return ret;
    }

    int odbc_mgr::term_env()
    {
        int ret = 0;

        if( SQL_NULL_HANDLE != m_hEnv )
        {
            SQLFreeHandle( SQL_HANDLE_ENV, m_hEnv );
            m_hEnv = SQL_NULL_HANDLE;
        }

        return ret;
    }

} // xos_odbc
